#include "cvertex.h"

#include <iostream>

CVertex::CVertex()
{
    this->setPosition(0.0, 0.0, 0.0);
    this->clearEdgelist();
    this->clearFaceList();
    this->m_bNormalSet = false;
    this->m_pParentMesh = NULL;
    this->m_OriginalPosition = this->m_Position;
}

CVertex::CVertex(const CVertex & ori)
{
    this->setPosition(ori.m_Position);
    this->m_pParentMesh = ori.m_pParentMesh;
    this->m_bNormalSet = ori.m_bNormalSet;
    this->m_OriginalPosition = ori.m_OriginalPosition;
    this->m_Normal = ori.m_Normal;
}

CVertex::CVertex(double dX, double dY, double dZ, CMesh * pParentMesh)
{
    this->setPosition(dX, dY, dZ);
    this->clearEdgelist();
    this->clearFaceList();
    this->m_bNormalSet = false;
    this->m_pParentMesh = pParentMesh;
    this->m_OriginalPosition = this->m_Position;
}

CVertex::CVertex(CPoint3f P, CMesh * pParentMesh)
{
    this->setPosition(P);
    this->clearEdgelist();
    this->clearFaceList();
    this->m_bNormalSet = false;
    this->m_pParentMesh = pParentMesh;
    this->m_OriginalPosition = this->m_Position;
}

double CVertex::getX()
{
    return this->m_Position.GetX();
}

double CVertex::getY()
{
    return this->m_Position.GetY();
}

double CVertex::getZ()
{
    return this->m_Position.GetZ();
}

CPoint3f CVertex::getPosition()
{
    return this->m_Position;
}

double CVertex::getOriginalX()
{
    return this->m_OriginalPosition.GetX();
}

double CVertex::getOriginalY()
{
    return this->m_OriginalPosition.GetY();
}

double CVertex::getOriginalZ()
{
    return this->m_OriginalPosition.GetZ();
}

CPoint3f CVertex::getOriginalPosition()
{
    return this->m_OriginalPosition;
}

CPoint3f CVertex::getNormal()
{
    return this->m_Normal;
}

bool CVertex::isNormalSet()
{
    return this->m_bNormalSet;
}

CMesh * CVertex::getParentMesh()
{
    return this->m_pParentMesh;
}

void CVertex::setX(double dX)
{
    this->m_Position.SetX(dX);
}

void CVertex::setY(double dY)
{
    this->m_Position.SetY(dY);
}
void CVertex::setZ(double dZ)
{
    this->m_Position.SetZ(dZ);
}

void CVertex::setPosition(double dX, double dY, double dZ)
{
    this->m_Position.Set(dX, dY, dZ);
}

void CVertex::setPosition(CPoint3f P)
{
    this->m_Position.Set(P.GetX(), P.GetY(), P.GetZ());
}

void CVertex::setNormal(double dX, double dY, double dZ)
{
    this->m_Normal.Set(dX, dY, dZ);
    this->m_bNormalSet = true;
}

void CVertex::setNormal(CPoint3f P)
{
    this->m_Normal.Set(P.GetX(), P.GetY(), P.GetZ());
    this->m_bNormalSet = true;
}

void CVertex::SetParentMesh(CMesh * pParent)
{
    this->m_pParentMesh = pParent;
}

void CVertex::addEdge(CEdge * pEdge)
{
    this->m_vEdgeList.push_back(pEdge);
}

void CVertex::addFace(CFace * pFace)
{
    this->m_vFaceList.push_back(pFace);
}

void CVertex::removeEdge(CEdge * pEdge)
{
    bool bFound = false;
    for (unsigned i = 0; !bFound && i < this->m_vEdgeList.size(); ++i)
    {
        if (pEdge == this->m_vEdgeList.at(i))
        {
            this->m_vEdgeList.erase(this->m_vEdgeList.begin() + i);
            bFound = true;
        }
    }
}

void CVertex::removeFace(CFace * pFace)
{
    bool bFound = false;
    for (unsigned i = 0; !bFound && i < this->m_vFaceList.size(); ++i)
    {
        if (pFace == this->m_vFaceList.at(i))
        {
            this->m_vFaceList.erase(this->m_vFaceList.begin() + i);
            bFound = true;
        }
    }
}

void CVertex::computeNormal()
{
    CPoint3f PTemp(0.0, 0.0, 0.0);
    for (unsigned i = 0; i < this->m_vFaceList.size(); ++i)
    {
        CFace * pFace = this->m_vFaceList.at(i);
        if (!pFace->isNormalSet())
            pFace->computeNormal();
        PTemp.Add(pFace->getNormal());
    }
    PTemp.Div((double)this->m_vFaceList.size());
    PTemp.normalize();
    this->setNormal(PTemp);
    this->m_bNormalSet = true;
}

void CVertex::clearEdgelist()
{
    this->m_vEdgeList.clear();
}

void CVertex::clearFaceList()
{
    this->m_vFaceList.clear();
}
